/*
 * Copyright (c) 2020 - present, Inspur Genersoft Co., Ltd.
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *       http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License. 
 */

package io.iec.edp.caf.multicontext.config;

import io.iec.edp.caf.commons.runtime.CafEnvironment;
import io.iec.edp.caf.multicontext.support.Module;
import io.iec.edp.caf.multicontext.support.YamlReader;
import lombok.var;
import org.springframework.core.env.Environment;
import org.springframework.util.StringUtils;

import java.util.ArrayList;
import java.util.LinkedHashMap;
import java.util.List;

/**
 * 并行配置读取
 * @author wangyandong
 */
public class ParallelConfigReader {

    //todo 配置文件路径 后期可考虑支持配置或传入
    private static final String configFile = "parallel-startup.yaml";
    /**
     * 构造函数
     */
    public ParallelConfigReader(){

    }

    public static ParallelSetting readParallelSetting(){
        //优先读取env
        if(!StringUtils.isEmpty(CafEnvironment.getEnvironment().getProperty("parallel.module.principle"))){
            return loadFromEnviorment();
        }else {
            //其次读取文件
            String fileName = CafEnvironment.getServerRTPath() + "/" + "runtime/" + configFile;
            return loadFromYaml(fileName);
        }
    }

    /**
     * 从parallel-startup.yaml文件重读取配置
     * @return
     */
    private static ParallelSetting loadFromYaml(String fileName){
        YamlReader reader= new YamlReader(fileName);
        ParallelSetting setting = new ParallelSetting();
        //底座路径
        List<String> platformPaths = reader.getValueByKey("parallel.base.paths", new ArrayList<>());
        setting.setBasePaths(platformPaths);
        //读取类型
        String value = reader.getValueByKey("parallel.module.principle","keyApp");
        setting.setPrinciple(Principle.valueOf(value));
        //读取路径查找范围
        List<String> paths = reader.getValueByKey("parallel.module.includes",new ArrayList<>());
        setting.setIncludes(paths);
        //读取排除范围
        paths = reader.getValueByKey("parallel.module.excludes",new ArrayList<>());
        setting.setExcludes(paths);

        //读取特殊的beans
        var beans = reader.getValueByKey("parallel.module.special-beans",new ArrayList<>());
        setting.setSpecilBeans(paths);

        //读取例外模块
        List<LinkedHashMap> modules = reader.getValueByKey("parallel.module.special-modules",new ArrayList<LinkedHashMap>());
        if(modules!=null && modules.size()>0){
            setting.setSpecialModules(new ArrayList<>());
            modules.forEach(map->{
                if(map.containsKey("name")){
                    SpecialModule sm = new SpecialModule();
                    sm.setName((String) map.get("name"));
                    sm.setIncludes((List)map.get("includes"));
                    setting.getSpecialModules().add(sm);
                }
            });
        }
        return setting;
    }

    /**
     * 基于application.yaml文件读取配置
     * @return
     */
    private static ParallelSetting loadFromEnviorment(){
        ParallelSetting setting = new ParallelSetting();
        Environment env = CafEnvironment.getEnvironment();

        //底座路径
        List<String> platformPaths = loadListFromEnvironment(env,"parallel.base.paths");
        setting.setBasePaths(platformPaths);
        //读取类型
        String value = env.getProperty("parallel.module.principle","keyApp");
        setting.setPrinciple(Principle.valueOf(value));
        //读取路径查找范围
        List<String> paths = loadListFromEnvironment(env,"parallel.module.includes");
        setting.setIncludes(paths);
        //读取排除范围
        paths = loadListFromEnvironment(env,"parallel.module.excludes");
        setting.setExcludes(paths);

        //读取特殊的bean
        var beans = loadListFromEnvironment(env,"parallel.module.special-beans");
        setting.setSpecilBeans(paths);

        //读取例外模块
        setting.setSpecialModules(new ArrayList<>());
        String Name_Format = "parallel.module.special-modules[%s].name";
        String Include_Format = "parallel.module.special-modules[%s].includes";
        int index =0;
        String keyOfName = String.format(Name_Format,index);
        String name = env.getProperty(keyOfName);
        while(!StringUtils.isEmpty(name)){
            SpecialModule sm = new SpecialModule();
            sm.setName(name);
            sm.setIncludes(loadListFromEnvironment(env,String.format(Include_Format,index)));
            setting.getSpecialModules().add(sm);

            index ++;
            keyOfName = String.format(Name_Format,index);
            name = env.getProperty(keyOfName);
        }
        return setting;
    }

    private static List<String> loadListFromEnvironment(Environment env, String keyPrefix) {
        String Key_Format = keyPrefix + "[%s]";
        int index = 0;
        String value = null;
        List<String> result = new ArrayList<>();
        do {
            String keyOfName = String.format(Key_Format, index);
            value = env.getProperty(keyOfName);
            if(!StringUtils.isEmpty(value)) {
                result.add(env.getProperty(keyOfName));
            }
            index++;
        }
        while (!StringUtils.isEmpty(value));
        return result;
    }
}
